package com.xl.activiti.demo.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhongwm
 */
@Slf4j
@RestController
@RequestMapping("/leave")
public class LeaveTaskController {

    @Resource
    private RepositoryService repositoryService;

    @Resource
    private RuntimeService runtimeService;

    @Resource
    private TaskService taskService;

    @Resource
    private HistoryService historyService;

    /**
     * 部署流程
     *
     * @return
     */
    @PostMapping("/deployment")
    public String deploymentLeaveDefinition() {
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("processes/leave.bpmn20.xml")
                .addClasspathResource("processes/leave.png")
                .name("请假审批流程")
                .deploy();
        log.info("部署流程成功. deployment:{}", deployment);
        return JSONUtil.toJsonStr(deployment);
    }

    /**
     * 查询流程定义
     * @param id
     * @return
     */
    @GetMapping("/definition/{id}")
    public String queryDefinition(@PathVariable("id") String id) {
        List<ProcessDefinition> definitionList = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(id)
                .orderByProcessDefinitionVersion()
                .desc()
                .list();
        return JSONUtil.toJsonStr(definitionList);
    }

    /**
     * 删除流程
     *
     * @param definitionKey
     * @return
     */
    @GetMapping("/delete/{key}")
    public String deleteDeployment(@PathVariable("key") String definitionKey) {
        ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(definitionKey)
                .singleResult();
        log.info("definition:{}", definition);
        if (definition != null) {
            repositoryService.deleteDeployment(definition.getDeploymentId());
            return "success";
        }
        return "not exist.";
    }

    /**
     * 创建审批流程实例
     *
     * @param definitionKey
     * @return
     */
    @GetMapping("/start/{key}")
    public String startProcess(@PathVariable("key") String definitionKey) {
        //查询流程是否存在
        ProcessDefinition definition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(definitionKey)
                .singleResult();
        if (definition != null) {
            //获取创建流程人的审批流程人，设置流程变量
            Map<String, Object> map = new HashMap<>();
            map.put("assignee0", "zhangsan");
            map.put("assignee1", "jack");
            map.put("assignee2", "rose");
            map.put("assignee3", "tom");

            ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(definitionKey, map);
            log.info("启动成功。 processInstance:{}", processInstance);
            return JSONUtil.toJsonStr(processInstance.getName());
        }
        return "not found data.";
    }

    /**
     * 查询所有正在处理的流程
     *
     * @return
     */
    @GetMapping("/query")
    public String queryTaskList() {
        List<Task> taskList = taskService.createTaskQuery().list();
        return JSONUtil.toJsonStr(taskList);
    }

    /**
     * 查询用户待处理任务
     *
     * @param username
     * @return
     */
    @GetMapping("/query/{username}")
    public String queryTasks(@PathVariable("username") String username) {
        List<Task> taskList = taskService.createTaskQuery().taskAssignee(username).list();
        return JSONUtil.toJsonStr(taskList);
    }

    /**
     * 处理任务
     * @param json
     * @return
     */
    @PostMapping("/complete")
    public String completeTask(@RequestBody JSONObject json) {
        String username = json.getStr("username");
        //任务id
        String taskId = json.getStr("taskId");
        if (StrUtil.isBlank(taskId)) {
            return "taskId invalid.";
        }
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task != null) {
            JSONObject params = json.getJSONObject("params");
            if (params != null) {
                //设置全部参数
                taskService.complete(taskId, params);
            } else {
                taskService.complete(taskId);
            }
            return "task completed.";
        }
        return "task not found.";
    }

    /**
     * 查询所有历史记录
     * @return
     */
    @GetMapping("/history")
    public String queryHistorys() {
        List<HistoricProcessInstance> processInstanceList = historyService.createHistoricProcessInstanceQuery().list();
        log.info("processInstanceList:{}", processInstanceList);
        List<HistoricTaskInstance> taskInstanceList = historyService.createHistoricTaskInstanceQuery().list();
        log.info("taskInstanceList:{}", taskInstanceList);
        List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery().list();
        log.info("activityInstanceList:{}", activityInstanceList);
        List<HistoricVariableInstance> variableInstanceList = historyService.createHistoricVariableInstanceQuery().list();
        log.info("variableInstanceList:{}", variableInstanceList);
        JSONObject jsonObj = new JSONObject();
        jsonObj.set("process", processInstanceList);
        jsonObj.set("task", taskInstanceList);
        jsonObj.set("activity", activityInstanceList);
        jsonObj.set("variable", variableInstanceList);
        return jsonObj.toString();
    }

    /**
     * 查询历史
     * @param definitionId
     * @return
     */
    @GetMapping("/history/definition/{definitionId}")
    public String queryHistoryDefinition(@PathVariable("definitionId") String definitionId) {
        List<HistoricProcessInstance> processInstanceList = historyService.createHistoricProcessInstanceQuery()
                .processInstanceId(definitionId).list();
        log.info("processInstanceList:{}", processInstanceList);
        List<HistoricTaskInstance> taskInstanceList = historyService.createHistoricTaskInstanceQuery()
                .processDefinitionId(definitionId).list();
        log.info("taskInstanceList:{}", taskInstanceList);
        List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery()
                .processDefinitionId(definitionId).list();
        log.info("activityInstanceList:{}", activityInstanceList);
        JSONObject jsonObj = new JSONObject();
        jsonObj.set("process", processInstanceList);
        jsonObj.set("task", taskInstanceList);
        jsonObj.set("activity", activityInstanceList);
        return jsonObj.toString();
    }

    /**
     * 查询流程实例历史
     * @param instanceId
     * @return
     */
    @GetMapping("/history/instance/{instanceId}")
    public String queryHistoryInfo(@PathVariable("instanceId") String instanceId) {
        List<HistoricProcessInstance> processInstanceList = historyService.createHistoricProcessInstanceQuery()
                        .processInstanceId(instanceId).list();
        log.info("processInstanceList:{}", processInstanceList);
        List<HistoricTaskInstance> taskInstanceList = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(instanceId).list();
        log.info("taskInstanceList:{}", taskInstanceList);
        List<HistoricActivityInstance> activityInstanceList = historyService.createHistoricActivityInstanceQuery()
                .processInstanceId(instanceId).list();
        log.info("activityInstanceList:{}", activityInstanceList);
        List<HistoricVariableInstance> variableInstanceList = historyService.createHistoricVariableInstanceQuery()
                .processInstanceId(instanceId).list();
        log.info("variableInstanceList:{}", variableInstanceList);
        JSONObject jsonObj = new JSONObject();
        jsonObj.set("process", processInstanceList);
        jsonObj.set("task", taskInstanceList);
        jsonObj.set("activity", activityInstanceList);
        jsonObj.set("variable", variableInstanceList);
        return jsonObj.toString();
    }

}
